﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFTetris.TetrisBoard
{
    /// <summary>
    /// Draws a tetris board.
    /// </summary>
    public partial class TetrisBoard : UserControl
    {
        public const int defaultWidth = 10;
        public const int defaultHeight = 20;
        public const int unitSizeInPixels = 20;

        private List<PointPositionInfo> pointsOnBoard = new List<PointPositionInfo>();
        private Dictionary<int, int> highPoints;

        public static DependencyProperty BoardWidthProperty = DependencyProperty.RegisterAttached("BoardWidth", typeof(int), typeof(TetrisBoard), new FrameworkPropertyMetadata(defaultWidth, FrameworkPropertyMetadataOptions.AffectsRender));
        public static DependencyProperty BoardHeightProperty = DependencyProperty.RegisterAttached("BoardHeight", typeof(int), typeof(TetrisBoard), new FrameworkPropertyMetadata(defaultHeight, FrameworkPropertyMetadataOptions.AffectsRender));

        public TetrisBoard()
        {
            InitializeComponent();
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            UpdateWidth();
            UpdateHeight();

            base.OnRender(drawingContext);
        }

        #region Public Properties

        public int BoardWidth
        {
            get { return (int)GetValue(BoardWidthProperty); }
            set
            {
                SetValue(BoardWidthProperty, value);
                UpdateWidth();
                TryInitHighPoints();
            }
        }

        private void TryInitHighPoints()
        {
            if (highPoints == null)
            {
                highPoints = new Dictionary<int, int>(BoardWidth);

                for (int i = 0; i < BoardWidth; i++)
                {
                    highPoints.Add(i, 0);
                }
            }
        }

        public int BoardHeight
        {
            get { return (int)GetValue(BoardHeightProperty); }
            set
            {
                SetValue(BoardHeightProperty, value);
                UpdateHeight();
            }
        }

        #endregion

        #region Private Methods

        private void UpdateWidth()
        {
            this.Width = BoardWidth * unitSizeInPixels;
        }

        private void UpdateHeight()
        {
            this.Height = BoardHeight * unitSizeInPixels;
        }

        #endregion

        #region Public Methods

        public void AddTetrisPiece(TetrisPiece piece, int column)
        {
            PointPositionInfo ppi = null;
            TryInitHighPoints();

            int height = 0, absoluteHeight;
            bool found;
            for (int i = column; i <= column + piece.PieceWidth; i++)
            {
                height = highPoints[i];

                found = true;
                for (int j = 0; j < piece.PieceWidth; j++)
                {
                    absoluteHeight = highPoints[column + j];

                    if (piece.DownBorderHeights[j] + height <= absoluteHeight)
                    {
                        found = false;
                        break;
                    }
                }

                if (found)
                {
                    for (int k = 0; k < piece.PieceWidth; k++)
                        for (int l = 0; l < piece.PieceHeight; l++)
                            if (piece.TetrisMapArray[k, l] == 1)
                            {
                                ppi = new PointPositionInfo() { PosRow = height + (piece.PieceHeight - l - piece.DownBorderHeights[i - column] + 1), PosColumn = k + column, Background = piece.PieceColor };
                                pointsOnBoard.Add(ppi);
                                AddRectangle(ppi);
                            }

                    for (int k = 0; k < piece.PieceWidth; k++)
                        highPoints[column + k] = (piece.UpBorderHeights[k] - piece.DownBorderHeights[i - column] + 1) + height;
                    break;
                }

            }
        }

        private void AddRectangle(PointPositionInfo ppi)
        {
            Rectangle r = new Rectangle() { Width = unitSizeInPixels, Height = unitSizeInPixels };
            r.Fill = ppi.Background;
            r.Stroke = Brushes.Black;
            r.StrokeThickness = 0.5;
            Canvas.SetLeft(r, ppi.PosColumn * TetrisBoard.unitSizeInPixels - 1);
            Canvas.SetTop(r, (BoardHeight - ppi.PosRow) * TetrisBoard.unitSizeInPixels - 1);
            cv.Children.Add(r);
        }

        #endregion
    }
}
